using System;
using System.Collections.Generic;
using System.Deployment.Application;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using EvoGame.Ceeforee.Helpers;
using System.Xml.Linq;
using System.Security.Cryptography;
using EvoGame.Ceeforee.CivilizationPanels;
using System.Xml;

namespace EvoGame.Ceeforee
{
    public enum CivX 
    {
        Vanilla,
        Warlords,
        BeyondTheSword
    }

	public enum Lang
	{
		English,
		French,
		German,
		Italian,
		Spanish
	}

    public partial class MainWin : Form
    {
		public string Version
		{
			get { return statusBar_Version.Text; }
			set { statusBar_Version.Text = value; }
		}
		public string Debug
		{
			get { return debugConsole.Text; }
			set
			{
				debugConsole.AppendText("\t------------"+DateTime.UtcNow.ToLongTimeString()+"-------------" + Environment.NewLine);
				debugConsole.AppendText(value + Environment.NewLine);
			}
		}
		public Mod LoadedMod
		{
			get { return loadedMod; }
		}

        public DirectoryInfo LoadedModDir;
        public CivX Mode;
		public Lang Language = Lang.English;

		private AssemblyName assem = new AssemblyName();
		private Version ver = new Version();
		private Dictionary<string, object> general_Options = new Dictionary<string, object>();
		private Dictionary<string, Panel> civ_options = new Dictionary<string, Panel>();
		private Mod loadedMod;
		Timer updateTimer = new Timer();

		public C4EDB civDB;

		public MainWin(CivX civMode)
        {
            InitializeComponent();

			loadedMod = new Mod(this, civMode);
			Helper.SetMWin(this);

			if (ApplicationDeployment.IsNetworkDeployed)
			{ ver = ApplicationDeployment.CurrentDeployment.CurrentVersion; }
			else
			{ ver = Assembly.GetEntryAssembly().GetName().Version; }
			assem = Assembly.GetEntryAssembly().GetName();
			Version = String.Format("{0}, Version {1}", assem.Name, ver.ToString());

			Mode = civMode;
			ModSelector modSelector = new ModSelector(this);
			modSelector.Show();

			#region Remove tabs still under development: Debug, Civilizations
			if (!GetLicence())
			{
				tabControl.TabPages.Remove(tab_Debug);
				tabControl.TabPages.Remove(tab_Civilizations);
			}
			#endregion

			LoadTab("General");
			LoadTab("Civilizations");

			Debug = "Finished Loading Application!";

			if (ApplicationDeployment.IsNetworkDeployed)
			{
				updateTimer.Interval = 15 * 60 * 1000;
				updateTimer.Tick += new System.EventHandler(CheckForUpdate);
				updateTimer.Start();
			}
        }

		private void CheckForUpdate(object sender, EventArgs e)
		{
			UpdateCheckInfo info = null;
			string message = "";

			ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;

			try
			{
				Debug = string.Format("Checking for Update at: {0}", ad.UpdateLocation);
				info = ad.CheckForDetailedUpdate();
			}
			catch (DeploymentDownloadException dde)
			{
				message = "The new version of the application cannot be downloaded at this time. \n\nPlease check your network connection, or try again later. Error: " + dde.Message;
			}
			catch (InvalidDeploymentException ide)
			{
				message = "Cannot check for a new version of the application. The ClickOnce deployment is corrupt. Please redeploy the application and try again. Error: " + ide.Message;
			}
			catch (InvalidOperationException ioe)
			{
				message = "This application cannot be updated. It is likely not a ClickOnce application. Error: " + ioe.Message;
			}

			if (info.UpdateAvailable)
			{
				Boolean doUpdate = true;

				if (!info.IsUpdateRequired)
				{
					DialogResult dr = MessageBox.Show("Update Now?", "Update Available", MessageBoxButtons.YesNo);
					if (!(DialogResult.Yes == dr))
					{
						doUpdate = false;
						updateTimer.Stop();
					}
				}
				else
				{
					// Display a message that the app MUST reboot. Display the minimum required version.
					MessageBox.Show("Ceeforee has detected a mandatory update from your current version to version " + info.MinimumRequiredVersion.ToString() + ". The application will now install the update and restart.", "Update Available", MessageBoxButtons.OK, MessageBoxIcon.Information);
				}

				if (doUpdate)
				{
					try
					{
						ad.Update();
						MessageBox.Show("The application has been upgraded, and will now restart.");
						Application.Restart();
					}
					catch (DeploymentDownloadException dde)
					{
						MessageBox.Show("Cannot install the latest version of Ceeforee. \n\nPlease check your network connection, or try again later. Error: " + dde);
					}
				}
				MessageBox.Show(message);
				Debug = message;
			}
		}

		private bool GetLicence()
		{
			string file = string.Format("{0}\\licence.evo", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
			Debug = "Loading licence file: " + file;
			FileStream lic;
			XmlReader xReader;
			try
			{
				lic = new FileStream(file, FileMode.Open, FileAccess.Read);
				xReader = XmlReader.Create(lic);
			}
			catch (Exception e)
			{
				Debug = "Error loading Licence file: " + e;
				return false;
			}
			if (File.Exists(file))
			{
				XElement licence = XDocument.Load(xReader).Root.Element("Ceeforee");
				string user = licence.Element("User").Value;
				string id = licence.Element("ID").Value;
				string hash = Helper.HashString(user);
				if (id == hash)
				{
					Version = string.Format("{0} | Debug Version licenced to: {1}", Version, user);
					return true;
				}
				else
				{
					Debug = "Licence File invalid";
					return false;
				}
			}
			else
			{
				Debug = "Licence file not found.";
				return false;
			}
		}

		private void LoadTab(string tab)
		{
			switch (tab)
			{
				case "General":
					general_Options.Add("Name", modName);
					general_Options.Add("Description", modDescription);
					general_Options.Add("AllowPublicMaps", allowPublicMaps);
					general_Options.Add("NoCustomArt", noCustomArt);
					general_Options.Add("NoCustomAssets", noCustomAssets);
					general_Options.Add("NoCustomScenario", noCustomScenario);
					general_Options.Add("NoTeams", noTeams);
					general_Options.Add("ForceGameOptions", forceGameOptions);
					general_Options.Add("ForceScenario", forceScenario);
					general_Options.Add("ForceStandardEra", forceStandardEra);
					general_Options.Add("ModularLoading", modularXML);
					general_Options.Add("SkipMainMenu", skipMainMenu);
					general_Options.Add("SinglePlayerOnly", singlePlayerOnly);
					general_Options.Add("ImageFile", imageFile);
					break;
				case "Civilizations":
					TreeNode tn  = new TreeNode("Cities");
					tn.Tag = new CitiesPanel(this);
					civOptions.Nodes.Add(tn);
					break;
				default:
					break;
			}
		}

        private void menu_System_Open_Click(object sender, EventArgs e)
        {
            ModSelector modSelector = new ModSelector(this);
            modSelector.Show();
        }

		private void menu_System_Save_Click(object sender, EventArgs e)
		{
			try
			{
				SaveSettings();
				if (selectedCiv != null) civDB.AddCiv(selectedCiv);
				civDB.Save();
			}
			catch(Exception err)
			{
				string message = String.Format("Error occurred: {0}\"{1}\"", Environment.NewLine, err.Message);
				Debug = message;
				MessageBox.Show(message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private void MainWin_FormClosed(object sender, FormClosedEventArgs e)
		{
			string file = string.Format("{0}\\Ceeforee.log", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
			FileStream log = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read);
			TextWriter txtWrite = new StreamWriter(log);
			txtWrite.Write(Debug);
			txtWrite.Close();
		}
	}
}